#!/usr/bin/evn python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   文件名称 :     __init__.py
   文件功能描述 :   功能描述
   创建人 :       小钟同学
   创建时间 :          2021/7/15
-------------------------------------------------
   修改描述-2021/7/15:
-------------------------------------------------
"""
import warnings
from typing import Union

from fastapi import FastAPI, Request

from afast_core.core_libs.cashews import CircuitBreakerOpen
from .http_exception import SnowyPermissionDenied
from ..infirmary_responses.orjson_response import *
from starlette.exceptions import HTTPException as StarletteHTTPException
from fastapi.exceptions import HTTPException as FastapiHTTPException
from fastapi.exceptions import RequestValidationError
from pydantic import ValidationError
from afast_core.core_errors_en.errors_template import _any_error, get_any_en_error


class SnowyApiExceptionHandler:
    def __init__(self, app=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if app is not None:
            self.init_app(app)

    def init_app(self, app: FastAPI):

        @app.exception_handler(ArithmeticError)
        async def exception_handler(request: Request, exc: ArithmeticError):
            # print("参数提交异常错误selfself", exc.infirmary_errors()[0].get('loc'))
            # 路径参数错误
            # 判断错误类型
            return SnowyArithmeticErrorException()

        @app.exception_handler(Exception)
        async def all_exception_handler(_, exc: Exception):
            '''
            全局的捕获抛出的HTTPException异常，注意这里需要使用StarletteHTTPException的才可以
            :param request:
            :param exc:
            :return:
            '''
            # log_msg = f"捕获到系统错误：请求路径:{gziprequest.url.path}\n错误信息：{traceback.format_exc()}"
            if isinstance(exc, StarletteHTTPException) or isinstance(exc, FastapiHTTPException):
                if exc.status_code == 405:
                    return SnowyMethodnotallowedException()
                if exc.status_code == 404:
                    return SnowyNotfoundException()
                elif exc.status_code == 429:
                    return SnowyLimiterResException()
                elif exc.status_code == 500:
                    return SnowyInternalErrorException()
                elif exc.status_code == 400:
                    # 有部分的地方直接的选择使用raise的方式抛出了异常，这里也需要进程处理
                    # raise HTTPException(HTTP_400_BAD_REQUEST, 'Invalid token')
                    return SnowyBadrequestException(message=exc.detail)

                return SnowyBadrequestException()
            else:
                # 其他内部的异常的错误拦截处理
                # logger.error(exc)
                # traceback.print_exc()
                return SnowyInternalErrorException()

        @app.exception_handler(StarletteHTTPException)
        async def http_exception_handler(_, exc: StarletteHTTPException):
            if exc.status_code == 405:
                return SnowyMethodnotallowedException()
            if exc.status_code == 404:
                return SnowyNotfoundException()
            elif exc.status_code == 429:
                return SnowyLimiterResException()
            elif exc.status_code == 500:
                return SnowyInternalErrorException(message=exc.detail)
            return SnowyBadrequestException(message=exc.detail)

        from .exception import SnowyBusinessException
        @app.exception_handler(SnowyBusinessException)
        async def BusinessException(_, exc: SnowyBusinessException):
            return SnowyBusinessExceptionResponse(http_status_code=exc.error_code, api_code=exc.code, message=exc.msg)

        # @app.exception_handler(RequestValidationError)
        # async def validation_exception_handler(_request: Request, exc: Union[RequestValidationError, ValidationError]):
        #     status_code = getattr(exc, "status_code", 400)
        #
        #     return SnowyParameterException(http_status_code=status_code,
        #                                    msg="参数校验错误",
        #                                    data=APIValidationError.from_pydantic(exc).dict(exclude_none=True))

        @app.exception_handler(RequestValidationError)
        async def validation_exception_handler(_request: Request, exc: Union[RequestValidationError, ValidationError]):
            status_code = getattr(exc, "status_code", 400)
            print("进来了吗？？？？？？",exc)
            return SnowyParameterException(http_status_code=200,
                                               message=get_any_en_error(_request,exc),
                                               data=None)


        # @app.exception_handler(RequestValidationError)
        # async def validation_exception_handler(_, exc: Union[RequestValidationError, ValidationError]):
        #     status_code = getattr(exc, "status_code", 400)
        #     headers = getattr(exc, "headers", None)
        #
        #     message = getattr(exc, "message", "Validation error.")
        #     if message and not any(
        #             [message.endswith("."), message.endswith("?"), message.endswith("!")]
        #     ):
        #         message = message + "."  # pragma: no cover
        #
        #     # raw_errors_to_fields
        #     # print(raw_errors_to_fields(exc.raw_errors))
        #     curr_model = None
        #     for top_err in exc.raw_errors:
        #         if hasattr(top_err.exc, "model"):
        #             curr_model = getattr(top_err.exc, "model")
        #             break
        #     if curr_model:
        #         for err in exc.errors():
        #             # 获取错误字段名称
        #             print(":错误字段名称:", err["loc"][1])
        #             #  获取错误的类型
        #             print(":错误的类型:", err["type"])
        #             # err["msg"]  配置错误信息
        #             print(":错误信息:",err["msg"])
        #             err["msg"] = curr_model.Config.error_msg[err["loc"][1]][err["type"]]
        #
        #     # data = {**{"message": message, "fields": fields}, **APIValidationError.from_pydantic(exc).dict(exclude_none=True)}
        #     # return SnowyParameterException(http_status_code=status_code,
        #     #                                data=APIValidationError.from_pydantic(exc).dict(exclude_none=True))
        #     return SnowyParameterException(http_status_code=status_code,msg=APIValidationError.from_pydantic_onlymessage(exc),
        #                                    data=None)

        @app.exception_handler(CircuitBreakerOpen)
        async def validation_exception_handler(_, exc: CircuitBreakerOpen):
            return SnowyCircuitBreakerOpenException()

        @app.exception_handler(SnowyBusinessException)
        async def action(_, exc: SnowyBusinessException):
            return SnowyBusinessExceptionResponse(http_status_code=200, api_code=500, message=exc.msg)

        @app.exception_handler(SnowyPermissionDenied)
        async def action(_, exc: SnowyPermissionDenied):
            # LOGIN_STATE_INVALID(30007, "您还未登录或登录失效，请重新登录！"),
            # PARAM_ERROR(30001, "参数错误"),
            #     DATA_NOT_EXIST(30002, "左翻右翻，数据竟然找不到了~"),
            #     ALREADY_EXIST(30003, "数据已存在了呀~"),
            #     REPEAT_SUBMIT(30004, "亲~您操作的太快了，请稍等下再操作~"),
            #     NO_PERMISSION(30005, "对不起，您无法访问此资源哦~"),
            #     LOGIN_STATE_INVALID(30007, "您还未登录或登录失效，请重新登录！"),
            #     FORM_REPEAT_SUBMIT(30009, "请勿重复提交");
            return SnowyBusinessExceptionResponse(http_status_code=200, api_code=30007, message=exc.detail)


def setup_snowy_ext_exception(app: FastAPI) -> None:
    pass
    SnowyApiExceptionHandler().init_app(app)
